home *** CD-ROM | disk | FTP | other *** search
- C.S.M.P. Digest Tue, 03 Nov 92 Volume 1 : Issue 205
- Today's Topics:
- Think C Posix library
- Wanted: Code fragment using FindFolder() to get prefs. folder
- MacTCP, ASR's and completion routine hell
- Getting a dialog in front
- MACSBUG Dcmd for "Shut Down"
- Best Debugger for MPW/C++?
- Restart @interrupt time with VN
- Parsing text files
- The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
- The digest is a collection of article threads from the internet newsgroup
- comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
- regularly and want an archive of the discussions. If you don't know what a
- newsgroup is, you probably don't have access to it. Ask your systems
- administrator(s) for details. (This means you can't post questions to the
- digest.)
- Each issue of the digest contains one or more sets of articles (called
- threads), with each set corresponding to a 'discussion' of a particular
- subject. The articles are not edited; all articles included in this digest
- are in their original posted form (as received by our news server at
- cs.uoregon.edu). Article threads are not added to the digest until the last
- article added to the thread is at least one month old (this is to ensure that
- the thread is dead before adding it to the digest). Article threads that
- consist of only one message are generally not included in the digest.
- The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
- [128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the
- file /pub/mac/csmp-digest/README before downloading any files. The most
- recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
- directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex
- archive has a mail server; send a message with the text '$MACarch help' (no
- quotes) to LISTSERV@ricevm1.rice.edu for more information.
- The digest is also available via email. Just send a note saying that you
- want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
- automatically receive each new issue as it is created. Sorry, back issues
- are not available through the mailing list.
- Send administrative mail to mkelly@cs.uoregon.edu.
- -------------------------------------------------------
- From: tim@maths.tcd.ie (Timothy Murphy)
- Subject: Think C Posix library
- Organization: Dept. of Maths, Trinity College, Dublin, Ireland.
- Date: Fri, 2 Oct 1992 17:09:08 GMT
- I recently ported a number of GNU programs to the Mac --
- including perl-4.035, rcs-5.6, diff-2.0 and patch-2.0.12u8 --
- using Think C.
- To avoid repetition, I wrote a library
- called, rather grandiosely, ThinkCPosix or just Posix.
- (I say "wrote", but in fact code for many of the functions
- was collected from PD archives.)
- The following note describes what this library is,
- and how it can be obtained and used.
- ===================== ThinkCPosix.tex =====================
- \documentstyle[rcs,a4,12pt]{article}
- % rcs.sty is available from ftp.uni-stuttgart.de
- % in the directory soft/tex/latex-style-supported .
- \RCS$Revision: 1.1 $
- \RCS$Date: 1992/09/14 14:28:23 $
- \catcode`\"=\active
- \def"#1"{{\tt #1}}
- \begin{document}
- \title{A Posix Library for Think C}
- \author{Timothy Murphy\\
- Trinity College Dublin\\
- ("tim@maths.tcd.ie")}
- \date{\RCSDate\\[2mm]
- (Version \RCSRevision)}
- \maketitle
- \begin{abstract}
- This library is intended to supplement
- the ANSI and Unix libraries provided with Think C,
- by supplying as many of the missing Posix functions as possible.
- The library was developed to assist in porting
- GNU programs to the Macintosh\footnotemark.
- \end{abstract}
- \footnotetext{To date the author has ported
- the following GNU programs to the Mac:
- "diff-1.15",
- "patch-2.012u6",
- "rcs-5.6",
- "bison-1.18",
- "flex-2.3.7",
- "perl-4.035".}
- \section{Status}
- This library is placed in the Public Domain.
- It may be used and modified freely---%
- though the author would be grateful
- for notification of any such modifications,
- and would prefer if his name and e-mail address
- were left on all files, to this end.
- \section{Availability}
- The library is available by anonymous FTP from "ftp.maths.tcd.ie"
- in the directory "pub/Mac/ThinkCPosix-1.1".
- The compiled library is contained in the file "Posix.hqx".
- The source files are archived in "ThinkCPosix.hqx".
- This includes the Think C project "Posix.$\pi$".
- \section{Acknowledgements}
- The author has used freely code in the archives
- pointed out to him,
- in particular code by:
- Guido van Rossum ("guido@cwi.nl"), and
- Mathias Neearcher.
- (Where code is taken more or less verbatim,
- this is indicated in the relevant files.)
- He is also grateful for assistance from:
- Kenneth Seah ("kseah@procyon.austin.tx.us"),
- Sak Wathanasin ("sw@network-analysis-ltd.co.uk"),
- John W. Hardin ("hardin@mcc.com"), and
- Gary J. Henderson ("gary@iscnvx.lmsc.lockheed.com")
- \section{Posix}
- The use of the term ``Posix'' may be misleading---%
- it is certainly not meant to imply that the functions satisfy
- any Posix standards
- (of which the author is largely ignorant).
- It is intended simply as a description
- of the kind of functions included---%
- namely, those Posix functions not included
- in the Think C ANSI or Unix libraries.
- Many of the functions
- (in particular those in the file "dummy.c")
- do no more than return an appropriate value,
- indicating success or failure, as deemed appropriate.
- \section{Compilation}
- To re-compile the library,
- the included project "Posix.$\pi$" can be used.
- Just choose the "Build Library" option
- in the "Project" menu.
- The author has all the ANSI options turned on,
- as well as "Require prototypes".
- The 4-byte int option and 68020 code option
- are turned off.
- \section{Usage}
- Any file using the library should
- \begin{verbatim}
- #include "ThinkCPosix.h"
- \end{verbatim}
- The header ("*.h") files should be placed somewhere
- in the Think C tree (ie below the Think C application).
- Whenever the "Posix" library is included,
- the Think C "MacTraps" library must also be included.
- (This could probably be avoided by abstracting
- the very few MacTraps functions called.
- But is that legal?)
- \section{Notes}
- These are a few random thoughts on some of the functions
- in the library.
- \begin{description}
- \item["alloca()"]
- This has been included to avoid duplication.
- Note that the prototype is "void *alloca(size\_t)",
- rather than "char *alloca(unsigned)".
- \item["dup()"]
- The functions "dup()" and "dup2()"
- (as implemented here)
- both close the original file after duplication.
- The reason for this is that Think C adopts the non-standard,
- if plausible, policy of including some file-functions
- (such as "close")
- as part of the file structure.
- So a "close(fd)" addressed to the original descriptor
- would also close the duplicate.
- (This may be a misunderstanding on the author's part.)
- \item["getpasswd()"]
- This (and one or two other functions)
- call "getlogin()" in the Think C Unix library
- to find the user's name.
- This latter must be set---%
- under System 7, at least---%
- in the "Sharing Setup" Control Panel,
- as described in the Macintosh Networking Reference manual.
- (I believe that under System 6 the username was changed
- on the Chooser panel.)
- \item["Open()"]
- The library includes a few ``substitute'' functions,
- eg "Perror()" and "Open()".
- The idea is that these can be used in place of
- "perror()" or "open()" by including the line
- \begin{verbatim}
- #define open Open
- \end{verbatim}
- (or equivalent) at a judicious point in the program---%
- probably at the end of the configuration file,
- "conf.h" or whatever.
- The function "Open(char*, int, ...)"
- allows "open()" to take more than 2 arguments
- (as seems increasingly the practice),
- although these extra arguments are ignored.
- \item["Perror()"]
- This gives a brief description of the error (if it can)
- rather than just the number as in "perror()".
- The Think C function "strerror()"---%
- which the author had not noticed---%
- may render this unnecessary.
- \end{description}
- \section{Gnu ports}
- In principle the files
- "patch.hqx", "diff.hqx", "perl.hqx", "ci.hqx", etc,
- in the directory "pub/Mac" at "ftp.maths.tcd.ie"
- contain the compiled applications.
- The source for these applications---%
- or rather, the diff-files from the standard distributions---%
- are in the appropriate subdirectory,
- eg "pub/Mac/diff-2.0".
- Unfortunately, none of these ports are yet documented properly.
- \section{Development}
- The author would be very grateful
- for any suggested improvements or extensions.
- Please send them to "tim@maths.tcd.ie".
- Any material used will be duly acknowledged.
- Implementation of functions related to
- "pipe", "exec" and "spawn"
- would be particularly useful.
- (The "exec()" function in the Think C Unix library
- ignores all arguments except for the application to be launched.
- It would be nice if these arguments could be properly passed---%
- as must surely be feasible.)
- \end{document}
- ===========================================================
- - --
- Timothy Murphy
- e-mail: tim@maths.tcd.ie
- tel: +353-1-2842366
- s-mail: School of Mathematics, Trinity College, Dublin 2, Ireland
- ---------------------------
- From: zimerman@phoenix.Princeton.EDU (Jacob Ben-david Zimmerman)
- Subject: Wanted: Code fragment using FindFolder() to get prefs. folder
- Organization: Princeton University
- Date: Thu, 1 Oct 1992 15:08:43 GMT
- Hi all. I'm sorry if this is a FAQ, but I'm having trouble figuring it
- out...I was wondering if anyone could provide me with a code fragment
- which illustrates how to use FindFolder() to get a VRefNum for the
- Preferences folder (and create on if it doesn't exist.) I am using
- THink C 5.0. In addition, I am more than a bit lost on exactly how to
- handle transferring a couple of hundred bytes to and from disk. For
- example, IM talks about passing a buffer to the disk routines. Is this
- a predefined buffer? Is it one I need to create myself? Does it have to
- be of a certain size? Any help is much appreciated! Thanks for your
- time and patience.
- - -JBZimmerman!
- 0.2 of a Mac programmer. :-) And working on it.
- - --
- ___________ |-Is that Scotch over there? Hold everything.
- || | -Sean Connery, The Russia House
- || ||acob Zimmerman!+> <zimerman@phoenix.Princeton.EDU> INTERNET
- \===/ | <zimerman@PUCC> BITNET
- +++++++++++++++++++++++++++
- From: oster@well.sf.ca.us (David Phillip Oster)
- Organization: Whole Earth 'Lectronic Link
- Date: Thu, 1 Oct 1992 16:20:22 GMT
- This is a fragment from one of my products.:
- OSErr InitialPreferencesLookUp(){
- Str255 s;
- LongInt ff;
- OSErr val;
- Integer prefVRef;
- LongInt prefDirId;
- SFReply reply;
- /* put the name of the preferences file in the reply record.
- GetIndString(reply.fName, kMainStrs, kDefaultS);
- if(noErr == Gestalt(gestaltFindFolderAttr, &ff) && (ff & (1L << gestaltFindFolderPresent))){
- val = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
- &prefVRef, &prefDirId);
- if(noErr == val){ val = FSOpenWD(prefVRef, prefDirId, 'ERIC', &reply.vRefNum); }
- if(noErr == val){ val = OpenIt(&reply); }
- /* do not close this working directory! */
- }else{
- /* initialize the Str255 to "\p:Preferences:" note colons. */
- GetIndString(s, kMainStrs, kPrefDirS);
- Concat(s, reply.fName); /* pin tail on name */
- StrMove(s, reply.fName); /* move result back to reply */
- reply.vRefNum = world.sysVRefNum;
- val = OpenIt(&reply);
- return val;
- ---------------------------
- From: ejohnson@void.ncsa.uiuc.edu (Eric E. Johnson)
- Subject: MacTCP, ASR's and completion routine hell
- Organization: University of Illinois at Urbana
- Date: Thu, 1 Oct 1992 17:01:18 GMT
- I've been working on a networked, role playing game. So those who can
- help will be helping to alleviate the relative dearth of games on the
- Macintosh.
- The game requires that there be frequent exchanges of data between the
- server and client. The amount of data is small, under 100 bytes, and
- I've been referring to the exchanges as the heartbeat. As an example,
- the heartbeat leaves the server, and is sent to the client. The
- client reads it in, processes the client's data, and sends it back to
- the server.
- The idea is to have the rate of exchange as high as possible. Since
- we are using a Unix based server, turn around time for the heartbeat
- on the server end is fairly fast. Our problem has been the Mac end.
- After some initial work on the game, I realized that using null events
- from WaitNextEvent to parcel out time for networking wasn't working
- all that well. Since there can be long delays between WaitNextEvents
- due to screen redraws, the networking can be very jittery. The
- intelligent was to use interrupts, which would work during screen
- redraws.
- MacTCP offers two types of notification routines. One routine, the
- ASR, calls a function that you specify when new data has arrived, when
- the connection is closing, or other similar events. The second
- notification routine is a routine that's called upon completion of an
- async routine.
- I tried writing the networking using ASR's alone, and another using
- async notification routines alone. Neither worked very well. The
- heartbeat would be exchanged for a while, but eventually a brutal
- crash would ensue. Unfortunately, the crash was never consistent so
- it was difficult to debug.
- Last night, I decided to rewrite the client end on the Mac to use both
- an ASR and an async completion routine. When the heartbeat arrives,
- MacTCP calls my ASR. In my ASR, I issue an *async* read with a
- completion routine pointing to my send routine. The ASR reads in the
- data, and exits fine. When the async read is done, the completion
- routine is called, which then sends back out data. The heartbeat in
- port is different from the heartbeat out port, which would eliminate
- any problems MacTCP would have with multiple async commands on the
- same port.
- This works, but comes to screaching halt on the sixteenth beat. The
- server sends out the sixteenth beat, and nothing ever comes back from
- the client. The client has consistently died on the 16th beat. By
- crash, I mean the mouse no longer responds to movements, but oddly
- enough, I'm not tossed into MacsBug.
- Entering MacsBug via a hardware interrupt reveals very little. 'SC6'
- claims a6 points to a bad stack frame. 'SC7' has the same report
- every time, with the last five entries being the same every time. One
- of the entries is labeled, _UnimplTrap. UnimplementedTrap? How bad
- is that?
- I've tried using MacsBug breakpoints to follow my interrupts, rather
- than using the Think C debugger. This is where things get weird. If
- I set an interrupt at my ASR, MacsBug will stop in the ASR when data
- arrives. I always continue since the interrupt supposedly will run 15
- more times. On the second return of the heartbeat from the server,
- MacsBug stops in the ASR. However, when I tell MacsBug to continue
- with execution, MacsBug doesn't break into the ASR anymore. However,
- the server does get the heartbeat back.
- Obvious problems...
- Am I preserving A5? The ASR's do that for you, and I've done
- so in my async completion code.
- Turned off optimizations in Think C? Yep.
- Got Think C 5.0.3 for the Quadra? Yep.
- Does MacsBug not deal to well with interrupts? Has anyone had any
- luck with networking at interrupt level? Has anyone tried to do
- anything similar to this? Do completed async calls somehow linger
- around in MacTCP? My thinking is that 16 beats is such a nice power
- of 2, and on the 16th beat, too many things are lingering around.
- Any suggestions?
- Eric Johnson
- +++++++++++++++++++++++++++
- From: oster@well.sf.ca.us (David Phillip Oster)
- Organization: Whole Earth 'Lectronic Link
- Date: Fri, 2 Oct 1992 07:34:13 GMT
- I have done this in a production system. My experience has been that networking
- is so slow, because of the potential of retransmits and time outs, that ANY
- useful network program must use asynch i/o and completion routines.
- tips:
- 1.) ignore the ASR(). it is very hard to get this to work right.
- 2.) ignore the MacTCP high level interfac e. It isn't async so it is a
- joke for anything real.
- 3.) Use a middle level interface that handles filling out the parameter
- block for you. This is pretty trivial to write. Embed the parameter block
- as the first field of a larger structure, similar to the way a WindowPeek
- has a GrafPort embedded in the front of it, but most things just look at
- the struct on the front.
- 4.) in your main application, statically allocate all the data structures
- you'll need. Statically allocate an array of queue records (See OSUtils
- chap of Inside mac vol 2 for more information on these.)
- 5.) Use the global CurrentA5 to inititialize the ioCurrentA5 field of
- your extended parameter block.
- 6.) Your completion routine should save the value of A5 in a local,
- set A5 from the ioCurrentA5 of the parameter block (passed in register A0
- I believe) and restore A5 on exit. Look in the file <SetUpA4.h> for
- inspiration.
- 7.) Your completion routine can communicate with your event loop by
- dequeuing queue records from the free list (See suggestion 4) and
- enqueuing them on a pending list. Enqueu() and Dequeue() are guaranteed
- safe to call at interrupt time.
- 8.) If you need more help, contact me. My consulting rates are $85.00 per
- hour.
- +++++++++++++++++++++++++++
- From: resnick@cogsci.uiuc.edu (Pete Resnick)
- Organization: University of Illinois at Urbana
- Date: Fri, 2 Oct 1992 13:57:03 GMT
- Of MacTCP, oster@well.sf.ca.us (David Phillip Oster) writes:
- >1.) ignore the ASR(). it is very hard to get this to work right.
- Complaint: Anyone who ignores the ASR ignores ICMP messages. *Don't*
- ignore the ASR; report and act on ICMP destination unreachables. If
- you attempt a TCPActiveOpen and get an ICMP destination unreachable,
- TCPAbort the open and report to the user instead of doing what most
- programs do, which is wait up to a minute for the damn thing to time
- >7.) Your completion routine can communicate with your event loop by
- >dequeuing queue records from the free list (See suggestion 4) and
- >enqueuing them on a pending list. Enqueu() and Dequeue() are guaranteed
- >safe to call at interrupt time.
- I like this one; very slick way of doing it. Thanks David. However, it
- doesn't solve the reponse time problem that Eric was having, i.e.
- having to wait for the WNE to complete. Anyone have any slick
- strategies for that?
- - --
- Pete Resnick (...so what is a mojo, and why would one be rising?)
- Graduate assistant - Philosophy Department, Gregory Hall, UIUC
- System manager - Cognitive Science Group, Beckman Institute, UIUC
- Internet: resnick@cogsci.uiuc.edu
- +++++++++++++++++++++++++++
- From: mandel@tmc.tulane.edu (Jeff E Mandel)
- Date: 2 Oct 92 15:16:35 GMT
- Organization: Tulane University School of Medicine
- In article <BvHyr4.J8D@news.cso.uiuc.edu> Pete Resnick,
- resnick@cogsci.uiuc.edu writes:
- >>7.) Your completion routine can communicate with your event loop by
- >>dequeuing queue records from the free list (See suggestion 4) and
- >>enqueuing them on a pending list. Enqueu() and Dequeue() are guaranteed
- >>safe to call at interrupt time.
- >I like this one; very slick way of doing it. Thanks David. However, it
- >doesn't solve the reponse time problem that Eric was having, i.e.
- >having to wait for the WNE to complete. Anyone have any slick
- >strategies for that?
- The "private event queue" approach is the best way I ever found to
- communicate between interrupt routines and "safe time". The advantage is
- that you can dequeue from your private event queue in a MenuHook or
- DragHook. It is also possible to break up your screen refresh into
- smaller segments and call the dequeue routine in the loop. Probably, you
- are drawing to a gWorld, then copying the gWorld to the screen; just
- divide the grafPort into an arbitray number of rects as wide as the
- screen, and copy each one of these to the screen, calling your dequeue
- routine each time. This will degrade screen performance a bit, but one
- way or another, you have to interleave your IO calls into the screen
- drawing, so doing it explicitly gives you more control over it. Besides,
- it will give your game that vertical wipe effect so popular in video
- arcade games :-).
- There is another way to do what Eric wants, as he really only needs to be
- able to queue another IO call, and can preallocate enough parameter
- blocks to suffice. The solution I employed in a different problem (but
- conceptually similar) was to have a very short completion routine which
- queued a deferred task, which did the processing. The deferred task fires
- "soon", but there is no guarantee that it will fire before the next
- interrupt, or not be interrupted itself, so you need some sort of guard
- structures; a spin lock or a semaphore or such, so you don't get confused
- about what has and hasn't been done. Why go to the trouble? The deferred
- task doesn't block other interrupts, so the mouse doesn't get that jumpy
- look (which you can tolerate while initializing a disk, but would drive
- your game players crazy).
- Hope this helps,
- Jeff E Mandel MD MS
- Associate Professor of Anesthesiology
- Tulane University School of Medicine
- New Orleans, LA
- mandel@vax.anes.tulane.edu
- ---------------------------
- From: karlberg@e.kth.se (KRILLE_KROKODIL)
- Subject: Getting a dialog in front
- Date: 1 Oct 92 23:32:07 GMT
- Organization: KTH, Royal Institute of Technology, School of Electrical Engineering
- When I start a program I've written in Think Pascal it's supposed to
- show a dialog before it enters the main loop. The wierd thing is that
- although I pass behind=POINTER(-1) when I call GetNewDialog it gets
- drawn behind all the other windows on the screen, as does the main
- window until I enter the main loop. Why is that and how do I get round
- Martin
- - -------------------------------------------------------------------------------
- If you have a living frog for breakfast,
- nothing worse can happen during the day.
- +++++++++++++++++++++++++++
- From: absurd@applelink.apple.com (Tim Dierks, software saboteur)
- Date: 2 Oct 92 18:56:03 GMT
- Organization: MacDTS Marauders
- In article <00961772.8D5273A0@e.kth.se>, karlberg@e.kth.se
- (KRILLE_KROKODIL) wrote:
- > When I start a program I've written in Think Pascal it's supposed to
- > show a dialog before it enters the main loop. The wierd thing is that
- > although I pass behind=POINTER(-1) when I call GetNewDialog it gets
- > drawn behind all the other windows on the screen, as does the main
- > window until I enter the main loop. Why is that and how do I get round
- > it?
- > Martin
- MultiFinder, and System 7, for resons unknown to me, don't bring an
- application to the foreground until its event loop starts up; you
- can force it to bring you forward by making a few event calls; the
- canonical sequence is to call EventAvail() three times; you'll
- then be brought to the front.
- Tim Dierks
- MacDTS, but I squeak with glee
- ---------------------------
- From: Joel Sumner <js17@cornell.edu>
- Subject: MACSBUG Dcmd for "Shut Down"
- Organization: Trapped at Cornell University
- Date: Mon, 28 Sep 1992 20:19:54 GMT
- Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug? I have
- powerbook 100 and the ONLY way to shut off the power is from the Finder
- ShutDown command (there is this thing about not having a power switch or
- a power cord to unplug that causes problems... <grin>). Occasionally,
- when I crash the thing, I don't want to wait for it to do a full re-boot
- just to select "Shut Down". Has anyone written a Macs Bug DCMD (or any
- other method from MacsBug) which will do the same thing? Not even a full
- OS shutdown, just a "Power Off" would be nice....
- - -Joel
- Joel Sumner
- js17@cornell.edu
- q4kx@cornella (Bitnet)
- - -----------------------------------------------------------
- .sig under construction (like the rest of Cornell)
- +++++++++++++++++++++++++++
- From: howes@cat15.cs.wisc.edu (Glenn Howes)
- Date: 28 Sep 92 22:22:20 GMT
- Organization: University of Wisconsin, Madison -- Computer Sciences Dept.
- In article <1992Sep28.201954.20830@mail.cornell.edu> Joel Sumner <js17@cornell.edu> writes:
- >Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug? I have
- >powerbook 100 and the ONLY way to shut off the power is from the Finder
- >ShutDown command (there is this thing about not having a power switch or
- >a power cord to unplug that causes problems... <grin>). Occasionally,
- >when I crash the thing, I don't want to wait for it to do a full re-boot
- >just to select "Shut Down". Has anyone written a Macs Bug DCMD (or any
- >other method from MacsBug) which will do the same thing? Not even a full
- >OS shutdown, just a "Power Off" would be nice....
- It appears to me that pressing both the interupt and the reset buttons and
- holding them simultaneously causes a shutdown. Can anybody confirm that
- this will also cause the heads to park?
- - --
- - ------------------------------------------------------------------
- Glenn R. Howes Internet: howes@bert.chem.wisc.edu
- author: Kermit Tool GH // Picard & Riker in '92
- - ------------------------------------------------------------------
- +++++++++++++++++++++++++++
- From: crod@cc.curtin.edu.au (Scott Kevill)
- Organization: Curtin University of Technology
- Date: Fri, 2 Oct 1992 01:40:06 GMT
- Hi Joel,
- If you didn't have a DCMD, you could always use the trap call
- (like the ExitToShell used in the old days of ROM mini-debuggers)
- as I do.
- At the debugger prompt, type :
- SM 0 3F3C 0 1 A895
- or with MacsBug, you can do this in one line :
- SM 0 3F3C 0 1 A895;G 0
- After using this plenty of times for a quick shutdown, especially
- on floppy systems, it is fairly quick to type and has the advantage
- of working on any debugger.
- Hope this helps !
- Scott
- +-----------------------+--------------------------------------+
- I Scott Kevill I "Be like me, be original" I
- I crod@cc.curtin.edu.au I -- Me I
- +-----------------------+--------------------------------------+
- In article <1992Sep28.201954.20830@mail.cornell.edu>, js17@cornell.edu (Joel Sumner) writes:
- > Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug? I have
- > powerbook 100 and the ONLY way to shut off the power is from the Finder
- > ShutDown command (there is this thing about not having a power switch or
- > a power cord to unplug that causes problems... <grin>). Occasionally,
- > when I crash the thing, I don't want to wait for it to do a full re-boot
- > just to select "Shut Down". Has anyone written a Macs Bug DCMD (or any
- > other method from MacsBug) which will do the same thing? Not even a full
- > OS shutdown, just a "Power Off" would be nice....
- > -Joel
- > Joel Sumner
- > js17@cornell.edu
- > q4kx@cornella (Bitnet)
- > -----------------------------------------------------------
- > .sig under construction (like the rest of Cornell)
- +++++++++++++++++++++++++++
- From: rjc@monet.ccs.itd.umich.edu (Robert John Churchill)
- Organization: University of Michigan
- Date: Fri, 2 Oct 1992 13:17:02 GMT
- In article <1992Oct2.104006.1@cc.curtin.edu.au>, crod@cc.curtin.edu.au
- (Scott Kevill) wrote:
- > If you didn't have a DCMD, you could always use the trap call
- > (like the ExitToShell used in the old days of ROM mini-debuggers)
- > as I do.
- > In article <1992Sep28.201954.20830@mail.cornell.edu>, js17@cornell.edu (Joel Sumner) writes:
- > > Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug?
- Go into Macsbug and type "G Power" :)
- ---------------------------
- From: D_Gladstone@cs.aukuni.ac.nz (David Gladstone)
- Subject: Best Debugger for MPW/C++?
- Date: 28 Sep 92 23:39:06 GMT
- Organization: Computer Science Dept., Auckland University.
- I am soon to be embarking on a project that will require the use of C++.
- Currently we have MPW C++ v3.1 and Zortech C++ v2.1 for MPW. The question
- I have is about debuggers. From what I've read in the August APDA
- catalogue, there are two options:
- SADE 1.3.2 : Good scripting, but does not appear to have support for class
- browsing etc.
- SOURCEBUG v1.0.1 : "Special support for debugging MacApp and object
- oriented code."
- "A browser interface to display the classes and methods
- of MacApp or an object oriented program."
- How do these products fare? Is the class browser in SourceBug better,
- worse, or on par with Think Pascal's (with which I am familiar)?
- Are there any alternative products on the market which are better?
- If SADE and SOURCEBUG are the only viable products, which should I buy?
- should I buy both?
- Either post or email your recommendations.
- Thank you.
- D_Gladstone@cs.aukuni.ac.nz // Dept of Computer Science, // In real life
- =============================// University of Auckland, // as opposed to
- Ph: (64) (9) 373-7599 x5336 // Private Bag 92019, // in a computer:
- Fax:(64) (9) 373-7453 // Auckland, New Zealand. // David Gladstone
- +++++++++++++++++++++++++++
- From: Bruce.Hoult@bbs.actrix.gen.nz
- Date: Fri, 2 Oct 1992 02:28:49 GMT
- Organization: Actrix Information Exchange
- In article <1992Sep28.233906.26728@cs.aukuni.ac.nz> David Gladstone <D_Gladstone@cs.aukuni.ac.nz> writes:
- > I am soon to be embarking on a project that will require the use of C++.
- > Currently we have MPW C++ v3.1 and Zortech C++ v2.1 for MPW. The question
- > I have is about debuggers. From what I've read in the August APDA
- > catalogue, there are two options:
- > SADE 1.3.2 : Good scripting, but does not appear to have support for class
- > browsing etc.
- > SOURCEBUG v1.0.1 : "Special support for debugging MacApp and object
- > oriented code."
- > "A browser interface to display the classes and methods
- > of MacApp or an object oriented program."
- I use both daily. I wouldn't want to be without either, although if I
- had to choose only one I think, uuuuuuhhhh, when you need SADE you
- *need* it.
- SourceBug is better for general noodling around. It's marginally
- better for tracing control-flow type problems. It's much better than
- SADE for checking the match between source code and machine code -- you
- can display two windows of the same function, one in source the other
- in ASM and you can set breakpoints or singlestep in either view at
- will. You can have continuously updated windows containing the values
- in registers *and* in high-level program variables at the same time.
- It's easier to drop down into MACSBUG and come back again than in SADE
- (actually I 've never figured out how to do that in SADE...).
- SourceBug is immeasurably better than SADE at tracing around the data
- of PascalObjects -- you can click on the name of a class and a list of
- all currently instantiated objects of that class appears. Clicking on
- an object shows the fields of that object.
- Like MPW itself, SADE is programmable. That means SADE vs SourceBug
- is a bit like MPW vs THINK. SADE has less built in than SourceBug,
- but you can probably add everything I listed in the previous paragraph
- to it if you take the time to write the necesary scripts. I use SADE
- less than SourceBug, but when I do use it it's for its repeatability,
- its non-object data examining ability or its memory-stomper catching.
- Ever have a bug that only shows up after you go through two dozen
- steps, then crashes the Mac? Get sick of manually steering your
- program through those steps time after time? With SADE you can write
- a little script that starts your program and runs it to a breakpoint,
- changes the values of a couple of variables or sets the PC to a
- different line (to simulate the effects of getting an event from the
- user, or otherwise guide the program), runs to another breakpoint etc
- etc until you get to the problem situation. OK, that takes a while to
- set up (especially with a certain misfeature added in SADE 1.3 (?)
- that makes you chain actions wiht onEntry actions instead of using a
- straight line script), but sometimes the alternatives are worse.
- SADE is also good for examining data that the .SYM file doesn't
- properly describe. My main example of that is a pseudo-template type
- (done using macros) I use extensively that stores a dynamic array of
- xxxx's in a handle. SourceBug just shows the whole array as a handle,
- but SADE can be convinced to show it as an array of xxxx's.
- The latest SADE (but you need ETO to get it) has the ability to use the MMU
- to protect areas of memory to catch memory stomping bugs. This can save
- lots of aggro sometimes.
- If you've got MPW and C++ (and therefore C) and are getting SADE and
- SourceBug you should probably consider getting the full ETO package instead.
- It's a tad expensive but it's pretty good.
- - -- Bruce
- - --
- Bruce.Hoult@bbs.actrix.gen.nz Twisted pair: +64 4 477 2116
- BIX: brucehoult Last Resort: PO Box 4145 Wellington, NZ
- "Cray's producing a 500 MIPS personal computer with 256MB RAM and 8 GB
- hard disk that fits in your pocket!" "Great! Is it PC compatible?"
- ---------------------------
- From: stud08@cc4.kuleuven.ac.be (Karl Pottie)
- Subject: Restart @interrupt time with VN
- Date: 28 Sep 92 12:52:19 GMT
- Organization: K.U.Leuven - Academic Computing Center
- I'm writing an init which reboots the mac after a system error. For this
- purpose, I call the toolbox routine Restart() at interrupt time. This
- works fine except when VM is running. When VM is running the mac simply
- blanks its screen and locks up. I tried using DeferUserFN(), but it didn't
- help.
- How do I reboot (restart) a macintosh at interrupt time ? Any quick
- and dirty methods ? Any clean method ?
- Please respond to me directly
- +++++++++++++++++++++++++++
- From: jpugh@apple.com (Jon Pugh)
- Date: 30 Sep 92 03:38:17 GMT
- Organization: Apple Computer, Inc.
- In article <1992Sep28.125124@cc4.kuleuven.ac.be>, stud08@cc4.kuleuven.ac.be
- (Karl Pottie) wrote:
- > Hi,
- > I'm writing an init which reboots the mac after a system error. For this
- > purpose, I call the toolbox routine Restart() at interrupt time. This
- > works fine except when VM is running. When VM is running the mac simply
- > blanks its screen and locks up. I tried using DeferUserFN(), but it didn't
- > help.
- > How do I reboot (restart) a macintosh at interrupt time ? Any quick
- > and dirty methods ? Any clean method ?
- We spent a good half an hour laughing about this one in DTS today. It even
- got posted to the unofficial "Wall of Shame".
- I think Baumwell's suggestion was best. Stuff the MrBusError number into
- the bus error exception vector, then execute that same bus error number.
- That way you get a double exception and the machine reboots.
- ---------------------------
- From: u2005681@ucsvc.ucs.unimelb.edu.au
- Subject: Parsing text files
- Date: 30 Sep 92 04:03:35 GMT
- Organization: The University of Melbourne
- Hi folks,
- I wonder if any of you people out there can give me some advice?
- I've been programming for quite a while but I havn't had much to do
- with the Mac file system and related toolbox calls.
- As part of a new application, I am trying to read a text file of numbers
- and strings into a series of variables. The idea is to use the numbers as
- co-efficients for a simulation and the strings as labels for various graphs.
- As I understand it, the Mac OS deals with text files as UNIX-C does with
- binary files ie you specify how many bytes to read and what buffer to read
- them into. But in the absence of a standard library, how is it possible to
- read numbers and strings of differing lengths?
- An explanation (or even some source code in C) would be most excellent.
- I appreciate your time and effort.
- C.Hofflin
- - ----------------------------------------------
- "Insert your own clever, deep and meaningful quote here"
- +++++++++++++++++++++++++++
- From: kdlee@milli.cs.umn.edu (Kevin D. Lee)
- Organization: University of Minnesota, Minneapolis, CSci dept.
- Date: Wed, 30 Sep 1992 14:46:24 GMT
- In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au> u2005681@ucsvc.ucs.unimelb.edu.au writes:
- >Hi folks,
- >I wonder if any of you people out there can give me some advice?
- >I've been programming for quite a while but I havn't had much to do
- >with the Mac file system and related toolbox calls.
- >As part of a new application, I am trying to read a text file of numbers
- >and strings into a series of variables. The idea is to use the numbers as
- >co-efficients for a simulation and the strings as labels for various graphs.
- >As I understand it, the Mac OS deals with text files as UNIX-C does with
- >binary files ie you specify how many bytes to read and what buffer to read
- >them into. But in the absence of a standard library, how is it possible to
- >read numbers and strings of differing lengths?
- >An explanation (or even some source code in C) would be most excellent.
- >I appreciate your time and effort.
- >C.Hofflin
- >----------------------------------------------
- >"Insert your own clever, deep and meaningful quote here"
- I handle parsing a text file by reading all of the data into a handle.
- My next step is to lock the handle and start to dereference it by assigning
- a char pointer to point to the first byte. I then use the sscanf function
- from ansi c to parse out the items that I am interested in. After each
- sscanf make sure you move your char pointer to the correct position. If
- this is to vague let me know and I will provide more details.
- Kevin Lee
- +++++++++++++++++++++++++++
- From: bpb9204@tamsun.tamu.edu (Brent)
- Organization: Texas A&M Univ., Inc.
- Date: Wed, 30 Sep 1992 14:50:12 GMT
- u2005681@ucsvc.ucs.unimelb.edu.au writes:
- |As part of a new application, I am trying to read a text file of numbers
- |and strings into a series of variables. The idea is to use the numbers as
- |co-efficients for a simulation and the strings as labels for various graphs.
- |As I understand it, the Mac OS deals with text files as UNIX-C does with
- |binary files ie you specify how many bytes to read and what buffer to read
- |them into. But in the absence of a standard library, how is it possible to
- |read numbers and strings of differing lengths?
- What do you mean, "absence of a standard library?" What are you using?
- |An explanation (or even some source code in C) would be most excellent.
- I don't know the format of what you want to read in, so you'll have to
- massage the following into your own form.
- The idea is to use your own buffering. You do this by either using an
- array or allocating (with NewPtr() or NewHandle() ) an appropriately-sized
- buffer. The size of the buffer is important - if you make it a multiple
- of the disk block size, your reads will be much faster. A good buffer
- size is 1024 or 2048 bytes. (Is a mac disk block 512 bytes? or 1024?)
- What you'll do is pass bits of your buffer to string conversion utilities
- like Str2Num. This will convert the string representation of a number
- into an Extended type. When you are reading a string, just copy characters
- from the buffer to your string array directly.
- Note: Str2Num takes a "DecStr" type, which is effectively an array
- of 255 characters. That's how long your number representation can be.
- When your buffer position is equal to the length of the buffer, it's time
- to read in another block of data.
- This idea isn't difficult to implement and can be easily done in an
- afternoon, for sure. Some C books mention buffering, if you need a reference.
- I decided to go ahead and write some simple stuff. Here is my 10 minute
- hack:
- - ------- pseudo-C follows
- char buffer[1024];
- int bufpos;
- int endoffile=0;
- LoadBuffer()
- OSErr err;
- long count = 1024;
- /* inputRefNum is reference number of a pre-opened input file **/
- err = FSRead( inputRefNum, &count, buffer); /* check error result */
- if (count == 0)
- endoffile = 1;
- bufpos = 0;
- ScanNumber(Extended *e, )
- *e = Str2Num( &buffer[bufpos]);
- /*** update buffer position ***/
- while( buffer[bufpos] is in {0-9eE+-} )
- bufpos++;
- /* Note: this routine does not take into account the situation like:
- early data in file...... 10.23e49 ....... later data in file
- buffer read n ---------------||----------- buffer read n+1 ...
- ScanString( char *s, int maxlen)
- while (maxlen--)
- if (bufpos == 1024) LoadBuffer();
- *s++ = buffer[bufpos++];
- if (buffer[bufpos] is some character that does not belong in a string)
- return;
- ParseFile()
- while (!endoffile)
- /* this will be a series of calls to ScanNumber() and ScanString()
- ** that you'll have to figger out.
- */
- - --
- - ------------------------------------------------------------------------------
- Brent P. Burton, N5VMG Department of Computer Science
- bpb9204@tamsun.tamu.edu Texas A&M University
- What are typical family values? Good buys at WalMart.
- +++++++++++++++++++++++++++
- From: Michael Hecht <Michael_Hecht@mac.sas.com>
- Date: Wed, 30 Sep 1992 16:47:29 GMT
- Organization: SAS Institute Inc.
- In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au> ,
- u2005681@ucsvc.ucs.unimelb.edu.au writes:
- >As part of a new application, I am trying to read a text file of
- >numbers and strings into a series of variables. The idea is to use the
- >numbers as co-efficients for a simulation and the strings as labels for
- >various graphs.
- I've written a routine that imports a tab-delimited text file in which
- the first record contains column names. You supply it with an FSSpec for
- the text file, a STR# id containing the column names you're looking for,
- and an action proc to be called for each row. It reads the data and for
- each row builds a string list of column values in the order you specified
- by the STR#. It then passes this info to the row action proc.
- I wrote it to use the Task Manager, so all the I/O could be async and
- reading/processing could take place in the background. This part could be
- easily removed, or replaced with Threads, however.
- If you're interested, let me know and I'll post it.
- - --Michael
- =======================================================================
- Michael P. Hecht | Internet: Michael_Hecht@mac.sas.com
- SAS Institute Inc.; Cary, NC USA | AppleLink: SAS.HECHT
- +++++++++++++++++++++++++++
- From: beard@toadflax.UCDavis.EDU (Patrick C. Beard)
- Date: 30 Sep 92 19:40:29 GMT
- Organization: UC Davis, EECS Division of Computer Science
- In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au>,
- u2005681@ucsvc.ucs.unimelb.edu.au writes:
- > Hi folks,
- > I wonder if any of you people out there can give me some advice?
- > I've been programming for quite a while but I havn't had much to do
- > with the Mac file system and related toolbox calls.
- > As part of a new application, I am trying to read a text file of numbers
- > and strings into a series of variables. The idea is to use the numbers as
- > co-efficients for a simulation and the strings as labels for various graphs.
- > As I understand it, the Mac OS deals with text files as UNIX-C does with
- > binary files ie you specify how many bytes to read and what buffer to read
- > them into. But in the absence of a standard library, how is it possible to
- > read numbers and strings of differing lengths?
- If you are programming in THINK C, use the ANSI library and save
- yourself a lot of work.
- With this library, you can open up files with fopen("filename", "r") and
- use fgets or fscanf
- to parse your input. Here's a fragment. Say your file has some numbers,
- all floats:
- 1.23 0.345 100.2
- [as many lines of this form as you like]
- A small program to read this would be:
- main()
- float a, b, c; // numbers we'll be reading in.
- FILE* f; // stdio file pointer.
- f = fopen("file", "r"); // open the file for reading.
- while (fscanf(f, "%f %f %f", &a, &b, &c) != EOF) { // read the numbers.
- printf("a = %f, b = %f, c = %f\n", a, b, c);
- fclose(f);
- Reading strings is a matter of using %s rather than %f, unless of course
- your strings
- have embedded white space, which makes it more complicated. This should
- get you started.
- Good luck!
- // Patrick C. Beard
- // Department of Computer Science, U. C. Davis
- // pcbeard@ucdavis.edu
- +++++++++++++++++++++++++++
- From: Michael Hecht <Michael_Hecht@mac.sas.com>
- Date: Fri, 2 Oct 1992 13:46:55 GMT
- Organization: SAS Institute Inc.
- In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au> ,
- u2005681@ucsvc.ucs.unimelb.edu.au writes:
- >An explanation (or even some source code in C) would be most excellent.
- In article <BvEHB5.JL4@unx.sas.com> Michael Hecht,
- Michael_Hecht@mac.sas.com writes:
- >If you're interested, let me know and I'll post it.
- Well, I guess five requests warrants my sending this source code around
- the world. :-)
- Import uses Task Manager 2.3, which includes AtTaskExit/TaskExit support.
- If you don't have this version, you need to get it. Or, you could change
- the TASK #define to 0.
- Use it in good health!
- - --Michael
- =======================================================================
- Michael P. Hecht | Internet: Michael_Hecht@mac.sas.com
- SAS Institute Inc.; Cary, NC USA | AppleLink: SAS.HECHT
- =======================================================================
- // /* Add these to the appropriate header file */
- // typedef struct {
- // short numStrings;
- // Str255 string;
- // } **StringListHandle;
- // typedef OSErr ( *RowActionProc )( StringListHandle rowData,
- // long refCon );
- // OSErr Import( FSSpecPtr file, short columnListID,
- // RowActionProc rowAction, long refCon );
- * Import() will read a tab-delimited text file given a file spec,
- * a list of column names to look for (via a STR# id), and an action
- * proc w/refCon to be executed for each row.
- * The column label string list should probably be purgeable.
- * This function is designed to be called from a task. If you don't
- * want to call this from a task, change the TASK #define to 0.
- * Michael Hecht (Michael_Hecht@mac.sas.com)
- * 1-oct-1992
- /* Change this to 0 if you're not using Task Manager 2.3 */
- #define TASK 1
- #if TASK
- #include "Task.h"
- #else
- #define TaskYield()
- #endif
- /* Size of our import buffer */
- #define kImportBufferSize 1024
- /* Context information needed for import */
- typedef struct {
- HParmBlkPtr pb;
- long bufIndex;
- Boolean endOfFile;
- short **columnMap;
- short nReqColumns;
- StringListHandle rowData;
- } ImportRecord, **ImportHandle;
- /* Import task exit routine. It cleans up all our storage, etc. */
- static void ImportExit( ImportHandle ctx )
- if(( *ctx )->rowData )
- DisposHandle(( Handle )( *ctx )->rowData );
- if(( *ctx )->columnMap )
- DisposHandle(( Handle )( *ctx )->columnMap );
- if(( *ctx )->pb ) {
- Ptr buffer;
- buffer = ( *ctx )->pb->ioParam.ioBuffer;
- if( buffer )
- DisposPtr( buffer );
- if(( *ctx )->pb->ioParam.ioRefNum )
- PBCloseSync(( ParmBlkPtr )(( *ctx )->pb ));
- DisposPtr(( Ptr )( *ctx )->pb );
- DisposHandle(( Handle )ctx );
- static OSErr TOpen( HParmBlkPtr pb )
- OSErr err;
- pb->ioParam.ioCompletion = 0;
- err = PBHOpenDFAsync( pb );
- if( err != noErr )
- return err;
- while( pb->ioParam.ioResult > 0 )
- TaskYield();
- return pb->ioParam.ioResult;
- static OSErr TRead( HParmBlkPtr pb )
- OSErr err;
- pb->ioParam.ioCompletion = 0;
- err = PBReadAsync(( ParmBlkPtr )pb );
- if( err != noErr )
- return err;
- while( pb->ioParam.ioResult > 0 )
- TaskYield();
- return pb->ioParam.ioResult;
- static OSErr SetIndString( ConstStr255Param s, StringListHandle strList,
- short i )
- short k;
- Size offset;
- StringPtr p;
- if( i <= 0 )
- return paramErr;
- /* Add strings if necessary */
- k = i - ( *strList )->numStrings;
- if( k > 0 ) {
- OSErr err;
- short j;
- /* Add enough length bytes to the end of the string list */
- offset = GetHandleSize(( Handle )strList );
- SetHandleSize(( Handle )strList, offset + k );
- err = MemError();
- if( err != noErr )
- return err;
- /* Initialize length bytes to 0 */
- p = ( StringPtr )*strList + offset;
- for( j = 0; j < k; j++ )
- *p++ = 0;
- ( *strList )->numStrings = i;
- /* Determine the offset to the requested string */
- offset = sizeof( short );
- p = ( *strList )->string;
- for( k = 1; k < i; k++ ) {
- Size length;
- length = p[ 0 ] + 1;
- offset += length;
- p += length;
- /* Replace the string */
- Munger(( Handle )strList, offset, 0, p[ 0 ] + 1, ( Ptr )s, s[ 0 ] + 1 );
- return MemError();
- static OSErr ReadField( ImportHandle ctx, StringPtr field, Boolean
- *endOfRecord )
- OSErr err;
- Ptr buffer;
- short length;
- char c;
- buffer = ( *ctx )->pb->ioParam.ioBuffer + ( *ctx )->bufIndex;
- length = 0;
- *endOfRecord = FALSE;
- err = noErr;
- for( ;; ) {
- /* If the buffer is depleted, read some more in */
- if(( *ctx )->bufIndex >= ( *ctx )->pb->ioParam.ioActCount ) {
- /* If we've already reached the end of file, break out */
- if(( *ctx )->endOfFile ) {
- err = eofErr;
- *endOfRecord = TRUE;
- break;
- /* Read the next buffer full */
- err = TRead(( *ctx )->pb );
- if( err != noErr ) {
- /* Remember if we hit end of file, and keep going */
- if( err == eofErr ) {
- err = noErr;
- ( *ctx )->endOfFile = TRUE;
- }
- /* Break out if any other read errors */
- else
- break;
- /* Reset index into buffer */
- ( *ctx )->bufIndex = 0;
- buffer = ( *ctx )->pb->ioParam.ioBuffer;
- /* Retrieve next character from buffer */
- c = *buffer++;
- ( *ctx )->bufIndex++;
- /* End of field? */
- if( c == '\t' )
- break;
- /* End of record? */
- if( c == '\r' ) {
- *endOfRecord = TRUE;
- break;
- /* Length exceeded? */
- if( length == sizeof( field ) - 1 )
- continue;
- /* Transfer to field */
- field[ ++length ] = c;
- /* Set string length */
- field[ 0 ] = length;
- return err;
- static OSErr ReadHeader( ImportHandle ctx, short columnListID )
- OSErr err;
- StringListHandle columnList;
- short i, nReqColumns, col;
- short **columnMap;
- Str255 columnName, findName;
- Boolean endOfRecord, found;
- /* Retrieve the string list */
- columnList = ( StringListHandle )GetResource( 'STR#', columnListID );
- if( !columnList ) {
- err = ResError();
- if( err == noErr )
- err = resNotFound;
- return err;
- /* Retrieve number of columns */
- nReqColumns = ( *columnList )->numStrings;
- ( *ctx )->nReqColumns = nReqColumns;
- /* Allocate column map */
- columnMap = ( short ** )NewHandle( 0 );
- if( !columnMap )
- return MemError();
- ( *ctx )->columnMap = columnMap;
- /* Read labels from first record */
- for( col = 1;; col++ ) {
- /* Let other tasks run */
- TaskYield();
- /* Read a field */
- err = ReadField( ctx, columnName, &endOfRecord );
- if( err != noErr )
- break;
- /* Map labels to column names */
- found = FALSE;
- for( i = 1; i <= nReqColumns; i++ ) {
- GetIndString( findName, columnListID, i );
- if( EqualString( columnName, findName, FALSE, FALSE )) {
- found = TRUE;
- break;
- /* If not found, then this column will be ignored */
- if( !found )
- i = 0;
- /* Append to column map */
- err = PtrAndHand(( Ptr )&i, ( Handle )columnMap, sizeof( i ));
- if( err != noErr )
- break;
- if( endOfRecord )
- break;
- if( err == eofErr )
- err = noErr;
- return err;
- static OSErr ReadData( ImportHandle ctx, RowActionProc rowAction, long
- refCon )
- OSErr err;
- short col, nReqColumns, nColumns;
- StringPtr p;
- short **columnMap, i;
- StringListHandle rowData;
- Boolean endOfRecord;
- Str255 field;
- columnMap = ( *ctx )->columnMap;
- nColumns = GetHandleSize(( Handle )columnMap )/sizeof( short );
- /* Allocate rowData string list */
- nReqColumns = ( *ctx )->nReqColumns;
- rowData = ( StringListHandle )NewHandle( sizeof( short ) + nReqColumns );
- if( !rowData )
- return MemError();
- ( *ctx )->rowData = rowData;
- /* Read rows until an error occurs */
- for( ;; ) {
- /* Initialize row data to nReqColumns empty strings */
- ( *rowData )->numStrings = nReqColumns;
- p = ( *rowData )->string;
- for( i = 0; i < nReqColumns; i++ ) {
- *p++ = 0;
- /* Read a row */
- for( col = 0, endOfRecord = FALSE; !endOfRecord; col++ ) {
- /* Let other tasks run */
- TaskYield();
- /* Read a field */
- err = ReadField( ctx, field, &endOfRecord );
- if( err != noErr )
- break;
- /* Skip excess unlabeled columns */
- if( col >= nColumns )
- continue;
- /* Get column index; skip unrecognized columns */
- i = ( *columnMap )[ col ];
- if( i == 0 )
- continue;
- /* Insert this field into the row data */
- err = SetIndString( field, rowData, i );
- if( err != noErr )
- break;
- /* Get out now if errors occurred */
- if( err != noErr )
- break;
- /* Call row action proc */
- err = ( *rowAction )( rowData, refCon );
- if( err != noErr )
- break;
- /* Reset row data for next row */
- SetHandleSize(( Handle )rowData, sizeof( short ) + nReqColumns );
- if( err == eofErr )
- err = noErr;
- return err;
- OSErr Import( FSSpecPtr file, short columnListID,
- RowActionProc rowAction, long refCon )
- OSErr err;
- ImportHandle ctx;
- short exitLevel;
- HParmBlkPtr pb;
- Ptr buffer;
- /* Allocate import context info */
- ctx = ( ImportHandle )NewHandle( sizeof( ImportRecord ));
- if( !ctx )
- return MemError();
- #if TASK
- /* Install exit routine */
- err = AtTaskExit(( TaskProcPtr )ImportExit, ( long )ctx, &exitLevel );
- if( err != noErr ) {
- DisposHandle(( Handle )ctx );
- return err;
- #endif
- /* Initialize context info */
- ( *ctx )->pb = 0;
- ( *ctx )->bufIndex = 0;
- ( *ctx )->endOfFile = FALSE;
- ( *ctx )->columnMap = 0;
- ( *ctx )->rowData = 0;
- /* Allocate the parameter block */
- pb = ( HParmBlkPtr )NewPtr( sizeof( HParamBlockRec ));
- if( !pb ) {
- err = MemError();
- goto errExit;
- ( *ctx )->pb = pb;
- /* Fill out parameter block for open */
- pb->ioParam.ioRefNum = 0;
- pb->ioParam.ioBuffer = 0;
- pb->ioParam.ioVRefNum = file->vRefNum;
- pb->fileParam.ioDirID = file->parID;
- pb->ioParam.ioNamePtr = file->name;
- pb->ioParam.ioVersNum = 0;
- pb->ioParam.ioPermssn = fsRdPerm;
- pb->ioParam.ioMisc = 0;
- /* Open the import file */
- err = TOpen( pb );
- if( err != noErr )
- goto errExit;
- /* Allocate the input buffer */
- buffer = NewPtr( kImportBufferSize );
- if( !buffer ) {
- err = MemError();
- goto errExit;
- /* Set up parameter block for reading */
- pb->ioParam.ioBuffer = buffer;
- pb->ioParam.ioReqCount = kImportBufferSize;
- pb->ioParam.ioActCount = 0;
- pb->ioParam.ioPosMode = fsAtMark;
- pb->ioParam.ioPosOffset = 0;
- /* Read the header */
- err = ReadHeader( ctx, columnListID );
- if( err != noErr )
- goto errExit;
- /* Read the data */
- err = ReadData( ctx, rowAction, refCon );
- errExit:
- #if TASK
- TaskExit( exitLevel );
- #else
- ImportExit( ctx );
- #endif
- return err;
- =======================================================================
- /* This example shows how you would create a task that calls Import */
- #include "Task.h"
- #define kColumnLabels 131
- static OSErr ImportRow( StringListHandle rowData, long refCon )
- /* Process the row data here */
- /* Return an error code (ie: userCanceledErr) to stop */
- return noErr;
- static void ImportTask( FSSpecPtr file )
- UnexpectedError( Import( file, kColumnLabels, ImportRow, 0 ));
- OSErr NewImportTask( FSSpecPtr file )
- /* Spawn a task to import the text file */
- return NewTask(( TaskProcPtr )ImportTask, ( long )file, 0 );
- ---------------------------
- End of C.S.M.P. Digest
- **********************
-